#include "Driver_ATIM.h"

static void Driver_ATIM_SetDutyCycle(uint32_t channel, uint8_t dutyCycle, bool isComplementary);
static void Driver_ATIM_DisableAllChannel(void);

static FL_ATIM_OC_InitTypeDef atimOCChannel1Init = { 0 };
static FL_ATIM_OC_InitTypeDef atimOCChannel2Init = { 0 };
static FL_ATIM_OC_InitTypeDef atimOCChannel3Init = { 0 };
static FL_ATIM_OC_InitTypeDef atimOCChannel4Init = { 0 };

static GPIOConfig atimGPIOConfigList[] = {
    [ATIM_GPIO_INDEX_YT1]  = { GPIOB,
                               { FL_GPIO_PIN_2, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                 FL_ENABLE, FL_DISABLE } },
    [ATIM_GPIO_INDEX_YTR1] = { GPIOB,
                               { FL_GPIO_PIN_4, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                 FL_ENABLE, FL_DISABLE } },
    [ATIM_GPIO_INDEX_YT2]  = { GPIOB,
                               { FL_GPIO_PIN_5, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                 FL_ENABLE, FL_DISABLE } },
    [ATIM_GPIO_INDEX_YTR2] = { GPIOB,
                               { FL_GPIO_PIN_3, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                 FL_ENABLE, FL_DISABLE } },
    [ATIM_GPIO_INDEX_YTRX] = { GPIOB,
                               { FL_GPIO_PIN_6, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                 FL_ENABLE, FL_DISABLE } },
    [ATIM_GPIO_INDEX_AM3]  = { GPIOB,
                               { FL_GPIO_PIN_7, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                 FL_ENABLE, FL_DISABLE } },
    [ATIM_GPIO_INDEX_AM4]  = { GPIOB,
                               { FL_GPIO_PIN_8, FL_GPIO_MODE_DIGITAL, FL_GPIO_OUTPUT_PUSHPULL, FL_DISABLE,
                                 FL_ENABLE, FL_DISABLE } },
};

/**
 * @brief 高级定时器初始化, 做为PWM输出
 *
 */
void Driver_ATIM_Init(void)
{
    FL_ATIM_InitTypeDef    atimInit;
    FL_ATIM_OC_InitTypeDef atimOCInit;

    /*---------------GPIO配置(仅需要配置输出引脚)----------------*/
    for (uint8_t i = 0; i < ATIM_GPIO_INDEX_MAX; ++i) {
        FL_GPIO_Init(atimGPIOConfigList[i].port, &(atimGPIOConfigList[i].gpioInit));
    }

    /*---------------时基单元配置----------------*/
    atimInit.clockSource       = FL_CMU_ATIM_CLK_SOURCE_APBCLK; // APB时钟源
    atimInit.prescaler         = 32 - 1;                        // 分频系数
    atimInit.counterMode       = FL_ATIM_COUNTER_DIR_UP;        // 向上计数模式
    atimInit.autoReload        = 100 - 1;                       // 自动重装载值
    atimInit.clockDivision     = FL_ATIM_CLK_DIVISION_DIV1;
    atimInit.repetitionCounter = 0;
    atimInit.autoReloadState   = FL_ENABLE;
    FL_ATIM_Init(ATIM, &atimInit);

    /*---------------输出比较配置----------------*/
    atimOCInit.OCMode       = FL_ATIM_OC_MODE_PWM1;
    atimOCInit.compareValue = 0;
    atimOCInit.OCPolarity   = FL_ATIM_OC_POLARITY_NORMAL;
    atimOCInit.OCState      = FL_DISABLE; // TODO
    atimOCInit.OCNState     = FL_DISABLE; // TODO
    atimOCInit.OCIdleState  = FL_ATIM_OC_IDLE_STATE_LOW;
    atimOCInit.OCNIdleState = FL_ATIM_OCN_IDLE_STATE_LOW;
    atimOCInit.OCNPolarity  = FL_ATIM_OCN_POLARITY_NORMAL;
    atimOCInit.OCFastMode   = FL_DISABLE;
    atimOCInit.OCETRFStatus = FL_DISABLE;
    atimOCInit.OCPreload    = FL_DISABLE; // 建议使能预装载

    // 在初始化前先清除相关标志位
    FL_ATIM_ClearFlag_CC(ATIM, FL_ATIM_CHANNEL_1); // YT1
    FL_ATIM_ClearFlag_CC(ATIM, FL_ATIM_CHANNEL_2); // YT2
    FL_ATIM_ClearFlag_CC(ATIM, FL_ATIM_CHANNEL_3); // YTRX、AM4
    FL_ATIM_ClearFlag_CC(ATIM, FL_ATIM_CHANNEL_4); // AM3
    FL_ATIM_ClearFlag_Break(ATIM);
    FL_ATIM_ClearFlag_Update(ATIM);
    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_1, &atimOCInit);
    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_2, &atimOCInit);
    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_3, &atimOCInit);
    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_4, &atimOCInit);

    /* 保存OC配置 */
    atimOCChannel1Init = atimOCInit;
    atimOCChannel2Init = atimOCInit;
    atimOCChannel3Init = atimOCInit;
    atimOCChannel4Init = atimOCInit;

    // 使能定时器
    FL_ATIM_Enable(ATIM);
    // 使能输出
    FL_ATIM_EnableALLOutput(ATIM);

    /* 初始默认关闭全部通道 */
    Driver_ATIM_DisableAllChannel();
}

/**
 * @brief 按照设定的占空比 使能或禁用 选择的通道
 *
 * @param atim
 * @param channel           通道号
 * @param isComplementary   是否为互补通道
 * @param dutyCycle         占空比
 * @param isEnable          是否使能
 */
void Driver_ATIM_SetChannelDutyAndState(void *atim, uint32_t channel, bool isComplementary,
                                        uint8_t dutyCycle, bool isEnable)
{
    FL_ATIM_OC_InitTypeDef atimOCInit = { 0 };

    /* 根据通道号选择对应结构体 */
    switch (channel) {
    case FL_ATIM_CHANNEL_1: atimOCInit = atimOCChannel1Init; break;
    case FL_ATIM_CHANNEL_2: atimOCInit = atimOCChannel2Init; break;
    case FL_ATIM_CHANNEL_3: atimOCInit = atimOCChannel3Init; break;
    case FL_ATIM_CHANNEL_4: atimOCInit = atimOCChannel4Init; break;
    }

    /* 当是互补输出时，需要设置OCNState为FL_ENABLE */
    if (isComplementary) {
        atimOCInit.OCNState = isEnable;
    }
    else {
        atimOCInit.OCState = isEnable;
    }

    Driver_ATIM_SetDutyCycle(channel, dutyCycle, isComplementary);

    /* 从全局变量更新局部变量的compareValue */
    switch (channel) {
    case FL_ATIM_CHANNEL_1: atimOCInit.compareValue = atimOCChannel1Init.compareValue; break;
    case FL_ATIM_CHANNEL_2: atimOCInit.compareValue = atimOCChannel2Init.compareValue; break;
    case FL_ATIM_CHANNEL_3: atimOCInit.compareValue = atimOCChannel3Init.compareValue; break;
    case FL_ATIM_CHANNEL_4: atimOCInit.compareValue = atimOCChannel4Init.compareValue; break;
    }

    FL_ATIM_OC_Init(ATIM, channel, &atimOCInit);

    // 立即生效新的占空比
    FL_ATIM_GenerateUpdateEvent(ATIM);
}

/**
 * @brief 设置定时器占空比
 *
 * @param channel    通道号
 * @param dutyCycle  占空比
 */
static void Driver_ATIM_SetDutyCycle(uint32_t channel, uint8_t dutyCycle, bool isComplementary)
{
    /* 限制占空比, 为了防止因为失误导致占空比为100，所以当大于100时限制占空比为50% */
    if (dutyCycle > FULL_DUTY_CYCLE) {
        dutyCycle = FULL_DUTY_CYCLE / 2;
    }

    // if (isComplementary) {
    //     LOG("src: %d, \n", dutyCycle);
    //     dutyCycle = FULL_DUTY_CYCLE - dutyCycle;
    //     LOG("dst: %d, \n", dutyCycle);
    // }

    switch (channel) {
    case FL_ATIM_CHANNEL_1:
        atimOCChannel1Init.compareValue = dutyCycle;
        FL_ATIM_WriteCompareCH1(ATIM, dutyCycle);
        break;
    case FL_ATIM_CHANNEL_2:
        atimOCChannel2Init.compareValue = dutyCycle;
        FL_ATIM_WriteCompareCH2(ATIM, dutyCycle);
        break;
    case FL_ATIM_CHANNEL_3:
        atimOCChannel3Init.compareValue = dutyCycle;
        FL_ATIM_WriteCompareCH3(ATIM, dutyCycle);
        break;
    case FL_ATIM_CHANNEL_4:
        atimOCChannel4Init.compareValue = dutyCycle;
        FL_ATIM_WriteCompareCH4(ATIM, dutyCycle);
        break;
    default: LOG("Driver_ATIM_SetDutyCycle(): Channel Error!\n");
    }
}

/**
 * @brief 关闭全部通道
 *
 */
static void Driver_ATIM_DisableAllChannel(void)
{
    atimOCChannel1Init.OCState  = FL_DISABLE;
    atimOCChannel1Init.OCNState = FL_DISABLE;
    atimOCChannel2Init.OCState  = FL_DISABLE;
    atimOCChannel2Init.OCNState = FL_DISABLE;
    atimOCChannel3Init.OCState  = FL_DISABLE;
    atimOCChannel3Init.OCNState = FL_DISABLE;
    atimOCChannel4Init.OCState  = FL_DISABLE;
    atimOCChannel4Init.OCNState = FL_DISABLE;

    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_1, &atimOCChannel1Init);
    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_2, &atimOCChannel2Init);
    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_3, &atimOCChannel3Init);
    FL_ATIM_OC_Init(ATIM, FL_ATIM_CHANNEL_4, &atimOCChannel4Init);
}
